package csrc

import (
	"bufio"
	"gitee.com/gcom/gbox/errors"
	"gitee.com/gcom/stockdock/comm"
	s "gitee.com/gcom/stockdock/core/support"
	"gitee.com/gcom/stockdock/crawler"
	"github.com/360EntSecGroup-Skylar/excelize"
	"golang.org/x/text/encoding/simplifiedchinese"
	"io"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

// ListSzse 获取深交所股票列表
func ListSzse(ctx s.TracerCtx) ([]*Stock, error) {
	var client = &http.Client{Timeout: 30 * time.Second}
	req, _ := http.NewRequest("GET",
		"http://www.szse.cn/api/report/ShowReport?SHOWTYPE=xlsx&CATALOGID=1110&TABKEY=tab1", nil)
	req.Close = true
	resp, err := client.Do(req)
	if err != nil {
		s.WriteErrEvent(ctx, "下载股票列表失败", err)
		return nil, err
	}
	defer resp.Body.Close()

	file, err := excelize.OpenReader(resp.Body)
	if err != nil {
		return nil, errors.Wrap(err, "打开深交所股票列表失败")
	}

	sheet := file.GetSheetName(1)
	rows, err := file.Rows(sheet)
	if err != nil {
		return nil, errors.Wrap(err, "打开深交所股票列表失败")
	}
	list := make([]*Stock, 0, 2000)
	first := true
	for rows.Next() {
		if first {
			first = false
			continue
		}
		r := rows.Columns()
		stock := Stock{
			Code:         r[5],
			Name:         r[6],
			FullName:     r[2],
			CompAddr:     r[4],
			ListDate:     comm.MustParseTime(r[7], comm.DefaultDatePattern),
			TotalShare:   comm.MustParseInt(r[8]),
			FloatShare:   comm.MustParseInt(r[9]),
			Area:         r[15],
			Province:     r[16],
			City:         r[17],
			Industry:     r[18][1:],
			IndustryCode: r[18][0:1],
			Website:      r[19],
		}
		stock.Exchange = comm.ExchangeOf(stock.Code)
		stock.Board = comm.BoardOf(stock.Code)
		list = append(list, &stock)
	}
	return list, nil
}

// ListSse 获取上海证券交易所股票列表
func ListSse(ctx s.TracerCtx) ([]*Stock, error) {
	return doListSse(ctx, 1)
}

// ListKcb 获取上海证券交易所科创板股票列表
func ListKcb(ctx s.TracerCtx) ([]*Stock, error) {
	return doListSse(ctx, 8)
}

// 1: 上证主板A股, 2: 上证主板B股, 8: 科创板
func doListSse(ctx s.TracerCtx, stockType int) ([]*Stock, error) {
	var client = &http.Client{Timeout: 30 * time.Second}
	req, _ := http.NewRequest("GET",
		"http://query.sse.com.cn/security/stock/downloadStockListFile.do?"+"stockType="+strconv.Itoa(stockType), nil)
	req.Header = map[string][]string{
		"User-Agent": {crawler.UserAgent},
		"Referer":    {"http://query.sse.com.cn"},
	}
	req.Close = true
	resp, err := client.Do(req)
	if err != nil {
		s.WriteErrEvent(ctx, "下载股票列表失败", err)
		return nil, err
	}
	defer resp.Body.Close()

	bread := simplifiedchinese.GB18030.NewDecoder().Reader(resp.Body)
	cread := bufio.NewReader(bread)
	list := make([]*Stock, 0, 2000)
	r := regexp.MustCompile("\\s+")
	first := true
	for {
		line, _, err := cread.ReadLine()
		if first {
			first = false
			continue
		}
		if len(line) > 0 {
			arr := r.Split(string(line), 6)
			stock := Stock{
				Code:     arr[2],
				Name:     arr[3],
				ListDate: comm.MustParseTime(arr[4], comm.DefaultDatePattern),
			}
			stock.Exchange = comm.ExchangeOf(stock.Code)
			stock.Board = comm.BoardOf(stock.Code)
			list = append(list, &stock)
		}

		if err != nil {
			if err == io.EOF {
				return list, nil
			}
			return list, errors.Wrap(err, "读取文件错误")
		}
	}
}
